#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;

const int maxn = 202;
const int inf = 1<<22;
int cost[maxn][maxn];
char map[maxn][maxn];
int tag[maxn][maxn];
int linked[maxn];
int slack[maxn];
int label_x[maxn], label_y[maxn];
bool visited_x[maxn], visited_y[maxn];
int nx, ny;

struct pos { int x, y; };

bool inrange(int x, int n) { return 0 <= x && x < n; }

void bfs(int u, int v, int n, int m)
{
	bool vis[n+1][m+1];
	int dis[n+1][m+1];
	fill(&vis[0][0], &vis[n][m], false);
	fill(&dis[0][0], &dis[n][m], inf);

	const int dir[4][2] = {{-1, 0}, {+1, 0}, {0, -1}, {0, +1}};
	queue<pos> q;
	{
		pos tmp;
		tmp.x = u; tmp.y = v;
		q.push(tmp);
	}
	dis[u][v] = 0;
	vis[u][v] = true;
	while (!q.empty()) {
		int x = q.front().x, y = q.front().y;
		q.pop();
		for (int i = 0; i < 4; i++) {
			int px = x + dir[i][0], py = y + dir[i][1];
			if (inrange(px, n) && inrange(py, m) && !vis[px][py]) {
				pos tmp;
				tmp.x = px; tmp.y = py;
				q.push(tmp);
				vis[px][py] = true;
				dis[px][py] = dis[x][y] + 1;
				if (map[px][py] == 'H')
					cost[tag[u][v]][tag[px][py]] = dis[px][py];
			}
		}
	}
}

void init_cost(int n, int m)
{
	vector<pos> man;
	nx = ny = 0;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++) {
			cin >> map[i][j];
			if (map[i][j] == 'm') {
				tag[i][j] = nx++;
				pos tmp;
				tmp.x = i; tmp.y = j;
				man.push_back(tmp);
			}
			if (map[i][j] == 'H')
				tag[i][j] = ny++;
		}

	fill(&cost[0][0], &cost[nx][ny], inf);
	for (int i = 0; i < nx; i++)
		bfs(man[i].x, man[i].y, n, m);
}

int find_max_edge()
{
	int max_edge = 0;
	for (int i = 0; i < nx; i++)
		for (int j = 0; j < ny; j++)
			if (cost[i][j] > max_edge) max_edge = cost[i][j];
	return max_edge;
}

void flip_cost(int x)
{
	for (int i = 0; i < nx; i++)
		for (int j = 0; j < ny; j++) cost[i][j] = x - cost[i][j];
}

void init_label()
{
	fill(label_x, label_x + nx, -inf);
	fill(label_y, label_y + ny, 0);
	for (int i = 0; i < nx; i++)
		for (int j = 0; j < ny; j++)
			if (cost[i][j] > label_x[i]) label_x[i] = cost[i][j];
}

bool hungarian_dfs(int u)
{
	visited_x[u] = true;
	for (int i = 0; i < ny; i++) {
		if (visited_y[i]) continue;
		int tmp = label_x[u] + label_y[i] - cost[u][i];
		if (tmp == 0) {
			visited_y[i] = true;
			if (linked[i] == -1 || hungarian_dfs(linked[i])) {
				linked[i] = u;
				return true;
			}
		} else
			if (slack[i] > tmp) slack[i] = tmp;
	}
	return false;
}

int min_km()
{
	int max_edge = find_max_edge();
	flip_cost(max_edge);
	init_label();
	fill(linked, linked + ny, -1);
	for (int i = 0; i < nx; i++) {
		fill(slack, slack + ny, inf);
		while (true) {
			fill(visited_x, visited_x + nx, false);
			fill(visited_y, visited_y + ny, false);
			if (hungarian_dfs(i)) break;
			int d = inf;
			for (int j = 0; j < ny; j++)
				if (!visited_y[j] && d > slack[j]) d = slack[j];
			for (int j = 0; j < nx; j++)
				if (visited_x[j]) label_x[j] -= d;
			for (int j = 0; j < ny; j++)
				if (visited_y[j]) label_y[j] += d;
				else				slack[j] -= d;
		}
	}
	int value = 0, count = 0;
	for (int i = 0; i < ny; i++)
		if (linked[i] != -1) {
			value += cost[linked[i]][i];
			count++;
		}
	return max_edge * count - value;
}

int main()
{
	int n, m;
	while (cin >> n >> m && !(n == 0 && m == 0)) {
		init_cost(n, m);
		cout << min_km() << endl;
	}
}

